package com.spc.car.service.project.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.spc.car.common.exception.CustomException;
import com.spc.car.data.domain.project.vo.ProjectTenderingSaveVO;
import com.spc.car.data.entity.project.*;
import com.spc.car.data.entity.sys.SysUser;
import com.spc.car.data.service.project.*;
import com.spc.car.service.domain.dto.ProjectTenderingRequiredDTO;
import com.spc.car.service.domain.dto.SectionRequiredDTO;
import com.spc.car.service.validate.ValidationResult;
import com.spc.car.service.domain.dto.ProjectFlowDTO;
import com.spc.car.service.project.BidProjectService;
import com.spc.car.service.util.ValidateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class BidProjectServiceImpl implements BidProjectService {

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ProjectTeamService projectTeamService;

    @Autowired
    private ProjectTenderingService projectTenderingService;

    @Autowired
    private ProjectTenderingSectionService sectionService;

    @Autowired
    private ProjectDocService projectDocService;

    private final static Map<String, String> biddingModes = new HashMap<>();
    static {
        biddingModes.put("OT", "openTenderingV3");//公开招标
        biddingModes.put("IB", "invitationForBid");//邀请招标
        biddingModes.put("CN", "competitiveNegotiation");//竞争性谈判
        biddingModes.put("CC", "competitiveConsultations");//竞争性磋商
        biddingModes.put("IP", "inquiryProcurement");//询价采购
        biddingModes.put("SS", "singleSourceProcurement");//单一来源采购
    }

    private final static Map<String, String> docTypeMapping = new HashMap<>();
    static {
        docTypeMapping.put("OT01", "01"); //预审文件 01
        docTypeMapping.put("OT", "02"); //公开招标文件 02
        docTypeMapping.put("IB", "03");  //邀请招标文件
        docTypeMapping.put("CN", "04");  //竞争磋商文件
        docTypeMapping.put("CC", "05");  //竞争谈判文件
        docTypeMapping.put("IP", "06");  //询价文件
        //docTypeMapping.put("N", "07");  //公告
        //docTypeMapping.put("B", "08");  //公示
        docTypeMapping.put("NR", "09");  //澄清/补遗

    }


    @Override
    @Transactional
    public ProjectTendering saveProjectTendering(@NotNull ProjectTenderingSaveVO projectTenderingSaveVO,
                                                 @NotNull SysUser operator) {
        ProjectTendering projectTendering = new ProjectTendering();
        if (null !=projectTenderingSaveVO.getId() && 0 < projectTenderingSaveVO.getId()){
            projectTendering = projectTenderingService.getById(projectTenderingSaveVO.getId());
            if (Objects.isNull(projectTendering)) {
                throw new CustomException("没有匹配的招标项目");
            }
            projectTendering.setModifyTime(new Date());
        }else {
            projectTendering.setCode(projectTenderingService.generateBiddingProjectCode());
            projectTendering.setProjectDepId(operator.getDeptId());
            projectTendering.setProjectManagerId(operator.getUserId());
            projectTendering.setProjectManagerName(operator.getNickName());

            ProjectTeam projectTeam = new ProjectTeam();
            projectTeam.setProjectTenderingCode(projectTendering.getCode());
            projectTeam.setUserAccount(operator.getUserName());
            projectTeam.setUserName(operator.getNickName());
            projectTeam.setProjectRoleId(1);
            projectTeam.setProjectRoleName("项目负责人");

            projectTeamService.save(projectTeam);
        }
        BeanUtils.copyProperties(projectTenderingSaveVO, projectTendering);
        projectTenderingService.saveOrUpdate(projectTendering);

        return projectTendering;
    }

    @Override
    public ProjectFlowDTO getStartProcessInfo(@NotBlank String projectTenderingCode) {
        ProjectTendering projectTendering = projectTenderingService.getOne(
                new QueryWrapper<ProjectTendering>()
                        .eq("code", projectTenderingCode));

        if (null == projectTendering) {
            throw new CustomException("没有匹配的招标项目");
        }

        //取关联项目
        Project project = new Project();
        if (null == project) {
            throw new CustomException("没有关联的项目信息");
        }

        //验证招标项目信息是否完全
        if (StringUtils.isNotBlank(project.getTenderee())) {
           throw new CustomException("没有招标人");
        }

        //是否存在标段信息
        int numOfTenderingSection = sectionService.count(
                new QueryWrapper<ProjectTenderingSection>()
                        .eq("project_tendering_code", projectTenderingCode));
        if (numOfTenderingSection < 1) {
            throw new CustomException("没有对应标段信息");
        }

        //招标项目团队是否存在
        int numOfTeamMember = projectTeamService.count(
                new QueryWrapper<ProjectTeam>()
                        .eq("project_tendering_code", projectTenderingCode));

        if (numOfTeamMember < 1) {
            throw new CustomException("未设置项目团队");
        }

        ProjectFlowDTO projectFlowDTO = new ProjectFlowDTO();
        if (null != projectTendering) {
            projectFlowDTO.setProjectName(projectTendering.getProjectName());
            projectFlowDTO.setProcessDefinitionKey(biddingModes.get(projectTendering.getTenderManner()));

            boolean isPreQual = "01".equals(projectTendering.getSeniorityCheck());
            String docType = docTypeMapping.get(projectTendering.getTenderManner());
            Map<String, Object> variables = new HashMap<>();
            variables.put("isPreQual", isPreQual);
            variables.put("docType", isPreQual ? "01" : docType);
            projectFlowDTO.setVariables(variables);

        }
        return projectFlowDTO;
    }

    @Override
    public boolean haveEnoughFiles(String projectTenderingCode, String docType) {
        if (StringUtils.isBlank(projectTenderingCode)
                || StringUtils.isBlank(docType)) {
            return false;
        }
        List<ProjectDoc> projectDocList = projectDocService.list(
                new QueryWrapper<ProjectDoc>()
                        .eq("project_tendering_code", projectTenderingCode)
                        .eq("doc_type", docType)
                        .eq("status", "A")
        );

        List <ProjectTenderingSection> sectionList = sectionService.listByTenderingCode(projectTenderingCode);
        if (CollectionUtils.isEmpty(projectDocList)
                || CollectionUtils.isEmpty(sectionList)) {
            return false;
        }

        if (projectDocList.stream()
                .filter(projectDoc -> "N".equals(projectDoc.getContentType()))
                .count() < 1) {
            //缺少公告
            return false;
        }

        List<String> sectionCodeList = projectDocList.stream()
                .filter(projectDoc -> null != projectDoc.getProjectTenderingSectionCode())
                .map(ProjectDoc::getProjectTenderingSectionCode)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(sectionCodeList)) {
            return false;
        } else {
            for(ProjectTenderingSection section : sectionList) {
                if (!sectionCodeList.contains(section.getSectionCode())) {
                    return false;
                }
            }
        }

        return true;
    }

    @Override
    public boolean haveCompleteInfo(String projectTenderingCode) {
        ProjectTendering projectTendering = projectTenderingService.getByCode(projectTenderingCode);
        if (null == projectTendering) {
            return false;
        }

        List<ProjectTenderingSection> sectionList = sectionService.listByTenderingCode(projectTenderingCode);
        if (CollectionUtils.isEmpty(sectionList)) {
            return false;
        }

        ProjectTenderingRequiredDTO tenderingRequiredDTO = new ProjectTenderingRequiredDTO();
        BeanUtils.copyProperties(projectTendering, tenderingRequiredDTO);
        ValidationResult tenderingResult = ValidateUtils.validateEntity(tenderingRequiredDTO);
        if (tenderingResult.isHasErrors()) {
            return false;
        }

        for(ProjectTenderingSection section : sectionList) {
            SectionRequiredDTO sectionRequiredDTO = new SectionRequiredDTO();
            BeanUtils.copyProperties(section, sectionRequiredDTO);
            ValidationResult sectionResult = ValidateUtils.validateEntity(sectionRequiredDTO);
            if (sectionResult.isHasErrors()) {
                return false;
            }
        }
        return true;
    }

}


